//C19:ep_19_10.cpp
// Listing --container class : map.
#include <iostream>
#include <ostream>
#include <string>
#include <map>
using namespace std;

class Student
{
    public:
        Student();
        Student(const string& name, const int age);
        Student(const Student& rhs);
        ~Student();

        void SetName(const string& name);
        string GetName() const;
        void SetAge(const int age);
        int GetAge() const;

        Student& operator=(const Student& rhs);
    private:
        string itsName;
        int itsAge;
};

Student::Student()
: itsName("New Student"), itsAge(15) {}

Student::Student(const string& name, const int age)
: itsName(name), itsAge(age) {} 

Student::Student(const Student& rhs)
: itsName(rhs.GetName()), itsAge(rhs.GetAge()) {}

Student::~Student(){}

void Student::SetName(const string& name)
{
    itsName = name;
}
string Student::GetName() const
{
    return itsName;
}

void Student::SetAge(const int age)
{
    itsAge = age;
}

int Student::GetAge() const
{
    return itsAge;
}

Student& Student::operator=(const Student& rhs)
{
    itsName = rhs.GetName();
    itsAge = rhs.GetAge();
    return *this;
}

ostream& operator<<(ostream& os, const Student& rhs)
{
    os << rhs.GetName() << " is " << rhs.GetAge() << " years old";
    return os;
}

// display map properties
template<class T, class A>
void ShowMap(const map<T, A>& v);

typedef map<string, Student> SchoolClass;

int main(void)
{
    Student Harry("Harry", 18);
    Student Sally("Sally", 15);
    Student Bill("Bill", 17);
    Student Peter("Peter", 16);

    SchoolClass MathClass;
    MathClass[Harry.GetName()] = Harry;
    MathClass[Sally.GetName()] = Sally;
    MathClass[Bill.GetName()] = Bill;
    MathClass[Peter.GetName()] = Peter;

    cout << "MathClass:" << endl;
    ShowMap(MathClass);

    cout << "We know that " << MathClass["Bill"].GetName()
         << " is " << MathClass["Bill"].GetAge()
         << " years old" << endl;
}

//display map properties
template<class T, class A>
void ShowMap(const map<T, A>& v)
{
    for (map<T, A>::const_iterator  ci = v.begin();
        ci != v.end(); ++ci)
    {
        cout << ci->first << ": " << ci->second << endl;
    }
    cout << endl;
}


